#include "Cilindro.h"

Cilindro::Cilindro(unsigned int cantLados)
	{
	if (cantLados < 3)
		this->cantidadLados = 8;
	else
		this->cantidadLados = cantLados;
	}

Cilindro::~Cilindro()
	{
	}


unsigned int Cilindro::getCantidadLados() const
	{
	return this->cantidadLados;
	}

void Cilindro::setCantidadLados(unsigned int cantLados)
	{
	this->cantidadLados = cantLados;
	}


void Cilindro::dibujar(int tiempoDurEscena)
	{
	glPushMatrix();

	// nStep: indica la cantidad de pasos que se discretizan en el modelado del cilindro.
	int nStep = 360 / this->cantidadLados;
	
	/*
	*	nPuntos: indica la cantidad de puntos que definen el cilindro. Son los pasados por parametro
	*	en el constructor, multiplicado por 2 porque son 2 tapas y sumados 2 por los vertices centrales de ambas.
	*/
	int nPuntos = this->cantidadLados * 2 + 2;
	
	// vertices: arreglo con las coordenadas de cada vertice que se incluye en el modelo.
	SVertex *vertices = new SVertex[nPuntos];
	
	// indices: arreglo que se inicializa con los indices a cada vertice.
	SIndex *indices = new SIndex[nPuntos];
	for (int i = 0; i < nPuntos; i++)
		indices[i].idx = i;

	int nVertice = 0;
	// Cargo en vertices los puntos de la circunferencia inferior del cilindro.
	for (int i= 0;i < 360; i+=nStep)
		{
		vertices[nVertice].x = cos(i*2*M_PI/360);
		vertices[nVertice].y = sin(i*2*M_PI/360);
		vertices[nVertice].z = 0.0;
		nVertice++;
		}

	// Cargo en vertices los puntos de la circunferencia superior del cilindro.
	for (int i= 0;i < 360; i+=nStep)
		{
		vertices[nVertice].x = cos(i*2*M_PI/360);
		vertices[nVertice].y = sin(i*2*M_PI/360);
		vertices[nVertice].z = 1.0;
		nVertice++;
		}

	// Cargo en vertices el origen de la tapa inferior del cilindro.
	vertices[nVertice].x = 0.0;	vertices[nVertice].y = 0.0;	vertices[nVertice].z = 0.0;
	nVertice++;

	// Cargo en vertices el origen de la tapa superior del cilindro.
	vertices[nVertice].x = 0.0;	vertices[nVertice].y = 0.0;	vertices[nVertice].z = 1.0;

	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(3, GL_DOUBLE, 0, vertices);


	// Dibujo con glDrawElements() la tapa inferior del cilindro.
	SIndex *tapaInf = new SIndex[this->cantidadLados+2];
	tapaInf[0].idx = indices[nPuntos-2].idx;
	for (unsigned int i = 0; i < this->cantidadLados; i++)
		tapaInf[i+1].idx = indices[i].idx;
	tapaInf[this->cantidadLados+1].idx = indices[0].idx;
	glDrawElements(GL_TRIANGLE_FAN, this->cantidadLados + 2, GL_UNSIGNED_BYTE, tapaInf);


	// Dibujo con glDrawElements() la tapa superior del cilindro.
	SIndex *tapaSup = new SIndex[this->cantidadLados+2];
	tapaSup[0].idx = indices[nPuntos-1].idx;
	for (unsigned int i = 0; i < this->cantidadLados; i++)
		tapaSup[i+1].idx = indices[i + this->cantidadLados].idx;
	tapaSup[this->cantidadLados + 1].idx = indices[this->cantidadLados].idx;
	glDrawElements(GL_TRIANGLE_FAN, this->cantidadLados + 2, GL_UNSIGNED_BYTE, tapaSup);

	
	// Dibujo con glDrawElements() la seccion del cilindro.
	SIndex *unionTapas = new SIndex[nPuntos];
	int j = 0;
	for (int i = 0; i < nPuntos - 2; i += 2)
		{
		unionTapas[i].idx = indices[j + this->cantidadLados].idx;
		unionTapas[i + 1].idx = indices[j].idx;
		j++;
		}
	unionTapas[nPuntos - 2].idx = indices[this->cantidadLados].idx;
	unionTapas[nPuntos - 1].idx = indices[0].idx;
	glDrawElements(GL_TRIANGLE_STRIP, nPuntos, GL_UNSIGNED_BYTE, unionTapas);

	glDisableClientState(GL_VERTEX_ARRAY);
	glPopMatrix();

	delete vertices;
	delete indices;
	delete tapaInf;
	delete tapaSup;
	delete unionTapas;
	}
